package com.gitee.wsl.common.ui.ext.brush

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color

/**
 *
 * @author Siddhesh Patil
 * Siddroid.com
 * @since 28-03-2021
 *
 * A utility class for mixing colors together to form gradients
 */

/**
 * Mix two colors together horizontally
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.horizontal(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.horizontalGradient(listOf(to, from))
    } else {
        Brush.horizontalGradient(listOf(from, to))
    }
}

/**
 * Mix two colors together vertically
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.vertical(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.verticalGradient(listOf(to, from))
    } else {
        Brush.verticalGradient(listOf(from, to))
    }
}

/**
 * Mix a list of colors horizontally
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.horizontal(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.horizontalGradient(colors.reversed())
    } else {
        Brush.horizontalGradient(colors)
    }
}

/**
 * Mix a list of colors vertically
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.vertical(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.verticalGradient(colors.reversed())
    } else {
        Brush.verticalGradient(colors)
    }
}


/**
 * Mix two colors from top left to bottom right
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.topLeftToBottomRight(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(listOf(to, from), start = Offset(0f, 0f))
    } else {
        Brush.linearGradient(listOf(from, to), start = Offset(0f, 0f))
    }
}

/**
 * Mix colors from top left to bottom right
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.topLeftToBottomRight(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(colors.reversed(), start = Offset(0f, 0f))
    } else {
        Brush.linearGradient(colors, start = Offset(0f, 0f))
    }
}

/**
 * Mix two colors from top to bottom
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.topToBottom(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            start = Offset(0f, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            start = Offset(0f, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    }
}

/**
 * Mix colors from top to bottom
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.topToBottom(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            start = Offset(0f, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    } else {
        Brush.linearGradient(
            colors,
            start = Offset(0f, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    }
}

/**
 * Mix two colors from bottom to top
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.bottomToTop(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            end = Offset(0f, 0f),
            start = Offset(0f, Float.POSITIVE_INFINITY)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            end = Offset(0f, 0f),
            start = Offset(0f, Float.POSITIVE_INFINITY)
        )
    }
}

/**
 * Mix colors from bottom to top
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.bottomToTop(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            end = Offset(0f, 0f),
            start = Offset(0f, Float.POSITIVE_INFINITY)
        )
    } else {
        Brush.linearGradient(
            colors,
            end = Offset(0f, 0f),
            start = Offset(0f, Float.POSITIVE_INFINITY)
        )
    }
}

/**
 * Mix two colors from left to right
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.leftToRight(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            start = Offset(0f, 0f),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            start = Offset(0f, 0f),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    }
}

/**
 * Mix colors from left to right
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.leftToRight(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            start = Offset(0f, 0f),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    } else {
        Brush.linearGradient(
            colors,
            start = Offset(0f, 0f),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    }
}

/**
 * Mix two colors from right to left
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.rightToLeft(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            end = Offset(0f, 0f),
            start = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            end = Offset(0f, 0f),
            start = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    }
}

/**
 * Mix colors from right to left
 * @param colors the list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.rightToLeft(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            end = Offset(0f, 0f),
            start = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    } else {
        Brush.linearGradient(
            colors,
            end = Offset(0f, 0f),
            start = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    }
}

/**
 * Mix two colors from bottom left to top right corner
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.bottomLeftToTopRight(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            start = Offset(0f, Float.POSITIVE_INFINITY),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            start = Offset(0f, Float.POSITIVE_INFINITY),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    }
}

/**
 * Mix colors from bottom left to top right corner
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.bottomLeftToTopRight(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            start = Offset(0f, Float.POSITIVE_INFINITY),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    } else {
        Brush.linearGradient(
            colors,
            start = Offset(0f, Float.POSITIVE_INFINITY),
            end = Offset(Float.POSITIVE_INFINITY, 0f)
        )
    }
}

/**
 * Mix two colors from top right to bottom left corner
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.topRightToBottomLeft(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            start = Offset(Float.POSITIVE_INFINITY, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            start = Offset(Float.POSITIVE_INFINITY, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    }
}

/**
 * Mix colors from top right to bottom left corner
 * @param colors the list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.topRightToBottomLeft(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            start = Offset(Float.POSITIVE_INFINITY, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    } else {
        Brush.linearGradient(
            colors,
            start = Offset(Float.POSITIVE_INFINITY, 0f),
            end = Offset(0f, Float.POSITIVE_INFINITY)
        )
    }
}

/**
 * Mix two colors from bottom right corner to top left corner
 * @param from the first color
 * @param to the second color
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.bottomRightToTopLeft(from: Color, to: Color, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            listOf(to, from),
            start = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY),
            end = Offset(0f, 0f)
        )
    } else {
        Brush.linearGradient(
            listOf(from, to),
            start = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY),
            end = Offset(0f, 0f)
        )
    }
}

/**
 * Mix colors from bottom right corner to top left corner
 * @param colors list of colors
 * @param reversed reverse the gradient
 * @return a new [Brush] for use in composables
 */
fun Brush.Companion.bottomRightToTopLeft(colors: List<Color>, reversed: Boolean = false): Brush {
    return if (reversed) {
        Brush.linearGradient(
            colors.reversed(),
            start = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY),
            end = Offset(0f, 0f)
        )
    } else {
        Brush.linearGradient(
            colors,
            start = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY),
            end = Offset(0f, 0f)
        )
    }
}